﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;

namespace EditorTable
{
	public class SimpleExampleWindow : EditorWindow
	{
		static private SimpleExampleWindow _instance = null;
		private bool isInited { get { return _instance != null; } }

		private TableView m_labelTableView = null;
		private TableView m_exampleTableView = null;

		[MenuItem("Test/SimpleExample")]
		public static void OpenSimpleExample()
		{
			if (_instance == null)
				_instance = GetWindow<SimpleExampleWindow>(false, "SimpleExample", true);
			else
				FocusWindowIfItsOpen(typeof(SimpleExampleWindow));
		}

		private void OnEnable()
		{
			InitIfNeedInit();
		}

		private void InitIfNeedInit()
		{
			if (isInited)
				return;

			_instance = this;
			InitTableView();
		}

		private void InitTableView()
		{
			InitLableTableView();
			InitSimpleExampleTableView();
		}

		private void InitLableTableView()
		{
			string[] strLabels = new string[] {
				"Lable1", "Lable2", "Lable3", "Lable4", "Lable5"
			};

			m_labelTableView = new SingleLabelTableView(strLabels);
			m_labelTableView.selectionChangedCallback += (int[] prevSelection, int[] newSelection) =>
			{
				ChangeSelLabel(prevSelection.Length > 0 ? prevSelection[0] : -1, newSelection[0]);
			};
		}

		private void ChangeSelLabel(int nPrevSel, int nNewSel)
		{
			Debug.LogFormat("{0}/{1}", nPrevSel, nNewSel);
		}

		private void InitSimpleExampleTableView()
		{
			ColumnState.CheckInput checkInput = (string strInput) => {
				return strInput.Length < 6;
			};

			ColumnState.GetData getData = () =>
			{
				return new string[] { "111", "222" };
			};

			ColumnState[] columnStates = new ColumnState[]
			{
				new ColumnState("Lable", ColumnType.emLabel),
				new ColumnState("String", ColumnType.emString),
				new ColumnState("Int", ColumnType.emInt),
				new ColumnState("Float", ColumnType.emFloat),
				new ColumnState("Dropdown", ColumnType.emDropdown, 80, getData),
				new ColumnState("Check", ColumnType.emCheck, 80, checkInput),
				new ColumnState("Button", ColumnType.emButton),
				new ColumnState("Toggle", ColumnType.emToggle),
			};

			MultiColumnHeader multiColumnHeader = new MultiColumnHeader(columnStates);
			m_exampleTableView = new SimpleExampleTableView(multiColumnHeader, new TableState(), new SimpleExampleTableViewData());
		}

		private void OnGUI()
		{
			EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
			EditorGUILayout.BeginVertical(GUILayout.Width(200), GUILayout.ExpandHeight(true));
			m_labelTableView.OnGUI();
			EditorGUILayout.EndVertical();

			EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
			m_exampleTableView.OnGUI();
			EditorGUILayout.EndVertical();
			EditorGUILayout.EndHorizontal();
		}

		private void OnDestroy()
		{
			_instance = null;
		}
	}

	public class SimpleExampleTableView : TableView
	{
		protected override float filterHeight => 16;

		public SimpleExampleTableView(MultiColumnHeader multiColumnHeader, TableState tableState, TableViewData viewData)
			: base(multiColumnHeader, tableState, viewData)
		{

		}

		protected override void OnFilterGUI(Rect filterRect)
		{
			float fButtonWidth = 200;

			Rect buttonRect = filterRect;
			buttonRect.width = fButtonWidth;
			if (GUI.Button(buttonRect, "Add a Row"))
				AddRowCountChange(() => { m_viewData.AddNewRow(); });
		}

		protected override void CellItemClick(int nRow, int nColumn)
		{
			switch (nColumn)
			{
				case 6:
					Debug.Log("Test");
					break;
			}
		}
	}

	public class SimpleExampleTableViewData : TableViewData
	{
		public class SimpleExampleRowData
		{
			public string	strLable		= "";
			public string	strString		= "";
			public int		nInt			= 0;
			public float	fFloat			= 0f;
			public int		nDropdown		= 0;
			public string	strCheck		= "";
			public bool		bToggle			= false;
		}

		public class SimpleExampleRowViewItem : RowViewItem
		{
			public SimpleExampleRowData rowData = null;

			public override int depth => -1;
			public override int columnCount => 5;
			public override string keyValue => rowData.strLable;

			public SimpleExampleRowViewItem(int nId, SimpleExampleRowData data) : base(nId)
			{
				this.rowData = data;
			}

			static readonly GUIContent cTestLabel = new GUIContent("Test");

			public override dynamic GetData(int nColumn)
			{
				switch (nColumn)
				{
					case 0:
						return rowData.strLable;
					case 1:
						return rowData.strString;
					case 2:
						return rowData.nInt;
					case 3:
						return rowData.fFloat;
					case 4:
						return rowData.nDropdown;
					case 5:
						return rowData.strCheck;
					case 6:
						return cTestLabel;
					case 7:
						return rowData.bToggle;
					default:
						throw new Exception("Error Column");
				}
			}

			public override void SetData(int nColumn, dynamic data)
			{
				switch (nColumn)
				{
					case 1:
						rowData.strString = data;
						break;
					case 2:
						rowData.nInt = data;
						break;
					case 3:
						rowData.fFloat = data;
						break;
					case 4:
						rowData.nDropdown = data;
						break;
					case 5:
						rowData.strCheck = data;
						break;
					case 7:
						rowData.bToggle = data;
						break;
					default:
						throw new Exception("Error Column");
				}
			}
		}

		public SimpleExampleTableViewData() : base(new SimpleExampleTableData())
		{

		}

		override protected RowViewItem GetViewDataRoot()
		{
			RootRowViewItem root = new RootRowViewItem(GetNewRowItemId());
			for (int nRow = 0; nRow < m_tableData.nRowCount; ++nRow)
			{
				SimpleExampleRowData data = new SimpleExampleRowData();
				data.strLable = m_tableData.GetData(nRow, 0);
				data.strString = m_tableData.GetData(nRow, 1);

				if (!int.TryParse(m_tableData.GetData(nRow, 2), out data.nInt))
					data.nInt = 0;

				if (!float.TryParse(m_tableData.GetData(nRow, 3), out data.fFloat))
					data.fFloat = 0;

				if (!int.TryParse(m_tableData.GetData(nRow, 4), out data.nDropdown))
					data.nDropdown = 0;

				data.strCheck = m_tableData.GetData(nRow, 5);

				if (!bool.TryParse(m_tableData.GetData(nRow, 6), out data.bToggle))
					data.bToggle = false;

				root.AddChild(new SimpleExampleRowViewItem(GetNewRowItemId(), data));
			}

			return root;
		}

		public override void AddNewRow(int nRow = -1)
		{
			SimpleExampleRowData data = new SimpleExampleRowData();
			AddNewRow(new SimpleExampleRowViewItem(GetNewRowItemId(), data), nRow);
		}
	}

	public class SimpleExampleTableData : ITableData
	{
		private string[,] data = null;

		public int nRowCount => 2;
		public int nColumnCount => 7;

		public SimpleExampleTableData()
		{
			RemakeData();
		}

		public string GetData(int nRow, int nColumn)
		{
			return data[nRow, nColumn];
		}

		public void SetData(int nRow, int nColumn, dynamic data)
		{
			data[nRow, nColumn] = data.ToString();
		}

		public void SaveData()
		{
			throw new NotImplementedException();
		}

		public void RemakeData()
		{
			data = new string[2, 7]
			{
				{ "Lable1", "String1", "1", "1.1", "0", "check1", "false" },
				{ "Lable1", "String1", "1", "1.1", "0", "check1", "true" },
			};
		}
	}
}
